#include "StdAfx.h"
#include <QxtCore/QxtLogger>
#include "VSqlQuery.h"

///////////////////////////////////////////////////////////////////////////////

//
void VSqlQuery_fieldsToRecord(const VSqlFieldList &fieldList,VSqlSharedRecordPtr &record)
{
	for (int i = 0; i < fieldList.count(); ++i)
		record->append(fieldList[i].value());
}

//
void VSqlQuery_fieldsPtrToRecord(const VSqlFieldPtrList &fieldPtrList,VSqlSharedRecordPtr &record)
{
	for (int i = 0; i < fieldPtrList.count(); ++i)
		record->append(fieldPtrList[i]->value());
}

//
void VSqlQuery_recordToFieldsPtr(const VSqlSharedRecordPtr &record,VSqlFieldPtrList &fieldPtrList)
{
	for (int i = 0; i < fieldPtrList.count(); ++i)
		fieldPtrList[i]->setValue((*record)[i]);
}

// VSqlQuery_procedure ////////////////////////////////////////////////////////

//
VSqlQuery_procedure::VSqlQuery_procedure(const QSqlDatabase& db)
	:m_query(db)
{
}

//
void VSqlQuery_procedure::prepare(const QString &sqlProcName,const VSqlFieldPtrList &sqlInParams)
{
	QString sFields;
	foreach (QSqlField *field,sqlInParams)
		sFields += ":" + field->name() + ",";

	sFields.remove(sFields.count()-1,1);

	QString sql =
		"execute procedure " + sqlProcName + "(" + sFields + ")";

	bool isOk = m_query.prepare(sql);
	Q_ASSERT(isOk == true);
}

//
void VSqlQuery_procedure::exec(const VSqlFieldPtrList &sqlInParams)
{
	foreach (QSqlField *field,sqlInParams)
		m_query.bindValue(field->name(),field->value());

	bool isOk = m_query.exec();
	Q_ASSERT(isOk == true);
}

//
bool VSqlQuery_procedure::next(VSqlFieldPtrList &sqlOutParams)
{
	if (!m_query.next())
		return false;

	foreach (QSqlField *field,sqlOutParams)
		field->setValue( m_query.record().value(field->name()) );

	return true;
}

// VSqlQuery_insert ///////////////////////////////////////////////////////////

//
VSqlQuery_insert::VSqlQuery_insert(const QSqlDatabase& db)
	:m_query(db) 
	,m_genId(db)
{
}

//
void VSqlQuery_insert::prepare(const QString &sqlTableName,const VSqlFieldList &sqlFieldsInsert)
{
	QString sFields,sValues;
	foreach (const QSqlField field,sqlFieldsInsert)
	{
		sFields +=       field.name() + ",";
		sValues += ":" + field.name() + ",";
	}

	sFields.remove(sFields.count()-1,1);
	sValues.remove(sValues.count()-1,1);

	QString sql =
		"insert into " + sqlTableName + "(" + sFields + ")\r\n"
		"values("	+ sValues + ")"
	;
	
	bool isOk = m_query.prepare(sql);
	Q_ASSERT(isOk == true);
}

//
void VSqlQuery_insert::exec(const QSqlField &idField,VSqlFieldPtrList &sqlFieldsInsert)
{
	QSqlField *insIdField = NULL;
	foreach (QSqlField *field,sqlFieldsInsert)
	{
		if (field->name() == idField.name())
		{
			insIdField = field;
			break;
		}
	}

	Q_ASSERT(insIdField != NULL);

	if (insIdField->isNull())
	{
		QVariant idItem = m_genId.exec();
		insIdField->setValue(idItem);
	}

	foreach (QSqlField *field,sqlFieldsInsert)
		m_query.bindValue(field->name(),field->value());

	bool isOk = m_query.exec();
	Q_ASSERT(isOk == true);
}

//
QVariant VSqlQuery_insert::execEx(const QSqlField &idField,VSqlFieldList &sqlFieldsInsert)
{
	QSqlField *insIdField = NULL;
	for (int i = 0; i < sqlFieldsInsert.count(); ++i)
	{
		QSqlField &field = sqlFieldsInsert[i];
		
		if (field.name() == idField.name())
		{
			insIdField = &field;
			break;
		}
	}

	Q_ASSERT(insIdField != NULL);

	if (insIdField->isNull())
	{
		QVariant idItem = m_genId.exec();
		insIdField->setValue(idItem);
	}

	foreach (const QSqlField field,sqlFieldsInsert)
		m_query.bindValue(field.name(),field.value());

	bool isOk = m_query.exec();
	Q_ASSERT(isOk == true);
	
	return insIdField->value();
}

// VSqlQuery_select ///////////////////////////////////////////////////////////

//
VSqlQuery_select::VSqlQuery_select(const QSqlDatabase& db)
	:m_query(db) 
{
}

//
void VSqlQuery_select::prepare
(
	const QString &sqlTableName,
	const VSqlFieldList &sqlFieldsSelect,
	const QString &sqlWhere,
	const VSqlFieldList &sqlFieldsOrderBy
)
{
	QString sFields;
	foreach (const QSqlField field,sqlFieldsSelect)
		sFields += field.name() + ",";

	sFields.remove(sFields.count()-1,1);

	QString sql =	" select " + sFields + " from " + sqlTableName;

	if (!sqlWhere.isEmpty())
		sql += " where " + sqlWhere;

	if (sqlFieldsOrderBy.count())
	{
		QString sOrderBy;
		foreach (const QSqlField field,sqlFieldsOrderBy)
			sOrderBy += field.name() + ",";

		sOrderBy.remove(sOrderBy.count()-1,1);
		sql += " order by " + sOrderBy;
	}

	bool isOk = m_query.prepare(sql);
	Q_ASSERT(isOk == true);
}

//
void VSqlQuery_select::exec(const VSqlFieldList &sqlFieldsWhere)
{
	foreach (const QSqlField field,sqlFieldsWhere)
		m_query.bindValue(field.name(),field.value());

	bool isOk = m_query.exec();
	Q_ASSERT(isOk == true);
}

//
bool VSqlQuery_select::next(VSqlFieldPtrList &sqlFieldsSelect)
{
	if (!m_query.next())
		return false;

	foreach (QSqlField *field,sqlFieldsSelect)
		field->setValue( m_query.record().value(field->name()) );

	return true;
}

// VSqlQuery_update ///////////////////////////////////////////////////////////

//
VSqlQuery_update::VSqlQuery_update(const QSqlDatabase& db)
	:m_query(db)
{
}

//
void VSqlQuery_update::prepare
(
	const QString &sqlTableName,
	const VSqlFieldList &sqlFieldsUpdate,
	const QString &sqlWhere
)
{
	QString sSet;
	foreach (const QSqlField field,sqlFieldsUpdate)
		sSet += field.name() + " = :" + field.name() + ",";

	sSet.remove(sSet.count()-1,1);

	QString sql 
		= " update " + sqlTableName
		+ " set "    + sSet
		+ " where "  + sqlWhere;

	bool isOk = m_query.prepare(sql);
	Q_ASSERT(isOk == true);
}

//
void VSqlQuery_update::exec
(
	const VSqlFieldList &sqlFieldsUpdate,
	const VSqlFieldList &sqlFieldsWhere
)
{
	foreach (const QSqlField field,sqlFieldsUpdate)
		m_query.bindValue(field.name(),field.value());

	foreach (const QSqlField field,sqlFieldsWhere)
		m_query.bindValue(field.name(),field.value());

	bool isOk =	m_query.exec();
	Q_ASSERT(isOk == true);
}

// VSqlQuery_delete ///////////////////////////////////////////////////////////

//
VSqlQuery_delete::VSqlQuery_delete(const QSqlDatabase& db)
	:m_query(db)
{
}

//
void VSqlQuery_delete::prepare
(
	const QString &sqlTableName,
	const QString &sqlWhere
)
{
	QString sql 
		= " delete from " + sqlTableName
		+ " where "       + sqlWhere;

	bool isOk =	m_query.prepare(sql);
	Q_ASSERT(isOk == true);
}

//
void VSqlQuery_delete::exec(const VSqlFieldList &sqlFieldsWhere)
{
	foreach (const QSqlField field,sqlFieldsWhere)
		m_query.bindValue(field.name(),field.value());

	bool isOk = m_query.exec();
	Q_ASSERT(isOk == true);
}
